﻿using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;


#if false
  [CallerMemberName]特性是4.5才有,需要向 .csproj 增加
  <PackageReference Include="System.Runtime">
  	<Version>4.0.0</Version>
  </PackageReference>
  <Reference Include="mscorlib.dll" />
#endif

namespace NFox.WPF
{
    /// <summary>
    /// 通知属性更改基类
    /// </summary>
    /// ViewModel需要通知界面时,需要继承<seealso cref="INotifyPropertyChanged"/>
    public class ViewModelBase : INotifyPropertyChanged
    {
        /// <summary>
        /// 属性值更改事件,初始化事件
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged = (send, e) => { };

        /// <summary>
        /// 通知属性更改
        /// </summary>
        /// <param name="propertyName">属性名</param>
#if AC2008 || NET40
        public void OnPropertyChanged(string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
#else 
        public void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        } 
#endif

        /// <summary>
        /// 设置属性函数,自动通知属性改变事件
        /// </summary>
        /// <typeparam name="T">属性类型</typeparam>
        /// <param name="storage">属性</param>
        /// <param name="value">属性值</param>
        /// <param name="propertyName">属性名</param>
        /// <returns>成功返回 <see langword="true"/>,反之 <see langword="false"/></returns>
#if AC2008 || NET40
        protected virtual bool SetProperty<T>(ref T storage, T value, string propertyName = null)
        {
            if (object.Equals(storage, value)) return false;

            storage = value;
            this.OnPropertyChanged(propertyName);

            return true;
        }
#else
        protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
        {
            if (object.Equals(storage, value)) return false;

            storage = value;
            this.OnPropertyChanged(propertyName);

            return true;
        }
#endif

        /// <summary>
        /// 创建命令
        /// </summary>
        /// <param name="executeMethod">要调用的命令函数委托</param>
        /// <returns>WPF命令</returns>
        protected RelayCommand CreateCommand(Action<object> executeMethod)
        {
            return CreateCommand(executeMethod, (o) => true);
        }

        /// <summary>
        /// 创建命令
        /// </summary>
        /// <param name="executeMethod">要调用的命令函数委托</param>
        /// <param name="canExecuteMethod">命令是否可以执行的委托</param>
        /// <returns>WPF命令</returns>
        protected RelayCommand CreateCommand(Action<object> executeMethod, Func<object, bool> canExecuteMethod)
        {
            return new RelayCommand(executeMethod, canExecuteMethod);
        }
    }
}
